﻿//*************************************************************************************************
// SelectTagParser.cs
// Owner: Herodotos Herodotou (t-herohe)
//
// A specialized parser the is used to extract the selected option from 'select' html tags
// located in some html document.
//
// Copyright(c) Microsoft Corporation, 2008
//*************************************************************************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebAndLoadTestPluginsAndRules
{
    class SelectTagParser
    {
        // ****************************************************************************
        // Public Methods
        // ****************************************************************************

        public SelectTagParser(string documentContent)
        {
            m_documentContent = documentContent;
        }

        /// <summary>
        /// Gets the selected option for every select statement
        /// </summary>
        /// <param name="documentContent">The HTML document to parse</param>
        /// <returns>Enumerable list of all selected options</returns>
        public IEnumerable<string> GetAllSelectedOptions(string selectTagName)
        {
            HtmlTagInnerTextParser parser = new HtmlTagInnerTextParser(m_documentContent);
            if (selectTagName == null)
            {
                foreach (InnerText selectInnerText in parser.GetInnerTextForHtmlTags("select", true, false, false))
                {
                    string selectedOption = GetSelectedOption(parser, selectInnerText);
                    if (selectedOption != null)
                    {
                        yield return selectedOption;
                    }
                }
            }
            else
            {
                foreach (InnerText selectInnerText in parser.GetInnerTextForHtmlTags("select", "name", selectTagName, true, false, false))
                {
                    string selectedOption = GetSelectedOption(parser, selectInnerText);
                    if (selectedOption != null)
                    {
                        yield return selectedOption;
                    }
                }

                foreach (InnerText selectInnerText in parser.GetInnerTextForHtmlTags("select", "id", selectTagName, true, false, false))
                {
                    string selectedOption = GetSelectedOption(parser, selectInnerText);
                    if (selectedOption != null)
                    {
                        yield return selectedOption;
                    }
                }
            }
        }

        // ****************************************************************************
        // Private Methods
        // ****************************************************************************

        /// <summary>
        /// Gets the selected option from a particular select statement
        /// </summary>
        /// <param name="parser">The parser working on the HTML document</param>
        /// <param name="selectInnerText">The inner text of the select statement</param>
        /// <returns>The selected option</returns>
        private string GetSelectedOption(HtmlTagInnerTextParser parser, InnerText selectInnerText)
        {
            string selectedOption = GetExplicitSelectedOption(parser, selectInnerText);
            if (selectedOption == null)
            {
                //A selected option was not found. Get the default option
                selectedOption = GetDefaultSelectedOption(parser, selectInnerText);
            }

            return selectedOption;
        }

        /// <summary>
        /// Gets the explicit selected option from a particular select statement
        /// </summary>
        /// <param name="parser">The parser working on the HTML document</param>
        /// <param name="selectInnerText">The inner text of the select statement</param>
        /// <returns>The selected option</returns>
        private string GetExplicitSelectedOption(HtmlTagInnerTextParser parser, InnerText selectInnerText)
        {
            foreach (InnerText optionInnerText in parser.GetInnerTextForHtmlTags("option", "selected", "selected",
                false, true, true, selectInnerText.BeginOffset, selectInnerText.EndOffset))
            {
                if (optionInnerText != null)
                {
                    return optionInnerText.Value;
                }
            }

            return null;
        }

        /// <summary>
        /// Gets the default i.e. first option from a particular select statement
        /// </summary>
        /// <param name="parser">The parser working on the HTML document</param>
        /// <param name="selectInnerText">The inner text of the select statement</param>
        /// <returns>The default selected option</returns>
        private string GetDefaultSelectedOption(HtmlTagInnerTextParser parser, InnerText selectInnerText)
        {
            foreach (InnerText optionInnerText in parser.GetInnerTextForHtmlTags("option",
                false, true, true, selectInnerText.BeginOffset, selectInnerText.EndOffset))
            {
                if (optionInnerText != null)
                {
                    return optionInnerText.Value;
                }
            }

            return null;
        }

        // ****************************************************************************
        // Public Data Members
        // ****************************************************************************

        private string m_documentContent;
    }
}
